package com.edu.whty.common.tools;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Map;


public class HttpsUtil {

	private static final Logger logger=LoggerFactory.getLogger(HttpsUtil.class);
	public HttpsUtil() {
		// TODO Auto-generated constructor stub
	}
	
	private static final String METHOD_POST = "POST";
	private static final String METHOD_GET = "GET";
	private static final String DEFAULT_CHARSET = "utf-8";

	public static String doPost(String url, String params,String netIp){
		long start = System.currentTimeMillis();
		String retStr = null;
		String exceptionMes = null;
		try {
			String ctype = "application/json;charset=" + DEFAULT_CHARSET;
			byte[] content = {};
			if (params != null) {
				content = params.getBytes(DEFAULT_CHARSET);
			}
			retStr = doPost(url, ctype, content, 3000, 3000,netIp);
		} catch (UnsupportedEncodingException e) {
			exceptionMes = e.getMessage();
			e.printStackTrace();
		} catch (Exception e) {
			exceptionMes = e.getMessage();
			e.printStackTrace();
		}
		long end = new Date().getTime();
		//外部接口日志
		String costTime = end-start+"";
		String body = "{}";
		if(null != params){
			body = params;
		}
		//请求返回
		String returnStr = null;
		if(null != retStr && retStr.trim().length() > 500){
			returnStr = retStr.substring(0, 500);
		}else{
			returnStr = retStr;
		}
		if(null != exceptionMes && exceptionMes.trim().length() > 500){
			exceptionMes = exceptionMes.substring(0, 500);
		}
		printElkLog(url,body,costTime,exceptionMes,returnStr,netIp,"未获取",null);
		return retStr;
	}

	public static String doPost(String url, String ctype, byte[] content,
			int connectTimeout, int readTimeout,String netIp) throws Exception {
		HttpsURLConnection conn = null;
		OutputStream out = null;
		String rsp = null;
		try {
			try {
				SSLContext ctx = SSLContext.getInstance("TLSv1.2");
				/*ctx.init(new KeyManager[0],
				new TrustManager[] { new DefaultTrustManager() },
				new SecureRandom());*/
				TrustManager[] trustAllCerts = {new TrustAllTrustManager()};
				ctx.init(new KeyManager[0],trustAllCerts,new SecureRandom());
				SSLContext.setDefault(ctx);

				conn = getConnection(new URL(url), METHOD_POST, ctype,netIp);
				conn.setHostnameVerifier(new HostnameVerifier() {
					@Override
					public boolean verify(String hostname, SSLSession session) {
						return true;
					}
				});
				conn.setConnectTimeout(connectTimeout);
				conn.setReadTimeout(readTimeout);
			} catch (Exception e) {
				throw e;
			}
			try {
				out = conn.getOutputStream();
				out.write(content);
				rsp = getResponseAsString(conn);
			} catch (IOException e) {
				throw e;
			}

		} finally {
			if (out != null) {
				out.close();
			}
			if (conn != null) {
				conn.disconnect();
			}
		}

		return rsp;
	}

	private static class DefaultTrustManager implements X509TrustManager {

		@Override
		public void checkClientTrusted(X509Certificate[] arg0, String arg1) {
		}

		@Override
		public void checkServerTrusted(X509Certificate[] arg0, String arg1) {
		}

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}

	}

	private static HttpsURLConnection getConnection(URL url, String method,
			String ctype,String netIp) throws IOException {
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod(method);
		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setRequestProperty("Accept", "text/xml,text/javascript,text/html");
		conn.setRequestProperty("User-Agent", "stargate");
		conn.setRequestProperty("Content-Type", ctype);
		if(null != netIp && IpUtils.isRightIP(netIp)){
			conn.setRequestProperty("x-forwarded-for", netIp);
		}
		return conn;
	}

	protected static String getResponseAsString(HttpURLConnection conn)
			throws Exception {
		String charset = getResponseCharset(conn.getContentType());
		InputStream es = conn.getErrorStream();
		if (es == null) {
			return getStreamAsString(conn.getInputStream());
		} else {
			String msg = getStreamAsString(es);
			if (StringUtils.isEmpty(msg)) {
				throw new IOException(conn.getResponseCode() + ":"
						+ conn.getResponseMessage());
			} else {
				throw new IOException(msg);
			}
		}
	}

	/**
	 * 从输入流中读取数据
	 * 
	 * @param inStream
	 * @return
	 * @throws Exception
	 */
	public static String getStreamAsString(InputStream inStream)
			throws Exception {
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while ((len = inStream.read(buffer)) != -1) {
			outStream.write(buffer, 0, len);
		}
		byte[] data = outStream.toByteArray();
		outStream.close();
		inStream.close();
		String result = new String(data, "UTF-8");// 将二进制流转为String

		return result;
	}

	/*
	 * private static String getStreamAsString(InputStream stream, String
	 * charset) throws IOException { try { BufferedReader reader = new
	 * BufferedReader(new InputStreamReader(stream, charset)); StringWriter
	 * writer = new StringWriter();
	 * 
	 * char[] chars = new char[256]; int count = 0; while ((count =
	 * reader.read(chars)) > 0) { writer.write(chars, 0, count); }
	 * 
	 * return writer.toString(); } finally { if (stream != null) {
	 * stream.close(); } } }
	 */

	private static String getResponseCharset(String ctype) {
		String charset = DEFAULT_CHARSET;

		if (!StringUtils.isEmpty(ctype)) {
			String[] params = ctype.split(";");
			for (String param : params) {
				param = param.trim();
				if (param.startsWith("charset")) {
					String[] pair = param.split("=", 2);
					if (pair.length == 2) {
						if (!StringUtils.isEmpty(pair[1])) {
							charset = pair[1].trim();
						}
					}
					break;
				}
			}
		}

		return charset;
	}
	
	public static String doGet(String uri,String netIp){
		long start = System.currentTimeMillis();
		String retStr = null;
		String exceptionMes = null;
        try {
			HttpsURLConnection httpsConn = getHttpsURLConnection(uri, METHOD_GET,netIp);
			retStr = getStringFromStream(httpsConn.getInputStream());
		} catch (IOException e) {
			exceptionMes = e.getMessage();
			e.printStackTrace();
		}
        long end = new Date().getTime();
		//外部接口日志
		String costTime = end-start+"";
		String body = "{}";
		//请求返回
		String returnStr = null;
		if(null != retStr && retStr.trim().length() > 500){
			returnStr = retStr.substring(0, 500);
		}else{
			returnStr = retStr;
		}
		if(null != exceptionMes && exceptionMes.trim().length() > 500){
			exceptionMes = exceptionMes.substring(0, 500);
		}
		printElkLog(uri,body,costTime,exceptionMes,returnStr,netIp,"未获取",null);
		return retStr = retStr;
    }
	
	private static HttpsURLConnection getHttpsURLConnection(String uri, String method,String netIp) throws IOException {
        SSLContext ctx = null;
        try {
            ctx = SSLContext.getInstance("TLSv1.2");
            /*ctx.init(new KeyManager[0],
			new TrustManager[] { new DefaultTrustManager() },
			new SecureRandom());*/
			TrustManager[] trustAllCerts = {new TrustAllTrustManager()};
			ctx.init(new KeyManager[0],trustAllCerts,new SecureRandom());
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        SSLSocketFactory ssf = ctx.getSocketFactory();

        URL url = new URL(uri);
        HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
        httpsConn.setSSLSocketFactory(ssf);
        httpsConn.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
        httpsConn.setRequestMethod(method);
        if(null != netIp && IpUtils.isRightIP(netIp)){
        	httpsConn.setRequestProperty("x-forwarded-for", netIp);
		}
        httpsConn.setDoInput(true);
        httpsConn.setDoOutput(true);
        
        //新增超时时限
		httpsConn.setReadTimeout(3000);
		httpsConn.setConnectTimeout(3000);
        
        return httpsConn;
    }
	
	private static String getStringFromStream(InputStream is) throws IOException {
        StringBuilder sb = new StringBuilder();
        byte[] b = new byte[1024];  
        int r_len = 0;  
        while ((r_len = is.read(b)) > 0) {  
            sb.append(new String(b, 0, r_len, "utf-8"));  
        } 
        return sb.toString();
    }
	
	public static String doPost1(String url, String params,String netIp){
		long start = new Date().getTime();
		String retStr = null;
		String exceptionMes = null;
		try {
			String ctype = "application/json;charset=" + DEFAULT_CHARSET;
			byte[] content = {};
			if (params != null) {
				content = params.getBytes(DEFAULT_CHARSET);
			}
			retStr = doPost1(url, ctype, content, 30000, 30000,netIp);
		} catch (UnsupportedEncodingException e) {
			exceptionMes = e.getMessage();
			e.printStackTrace();
		} catch (Exception e) {
			exceptionMes = e.getMessage();
			e.printStackTrace();
		}
		long end = new Date().getTime();
		//外部接口日志
		String costTime = end-start+"";
		String body = "{}";
		if(null != params){
			body = params;
		}
		//请求返回
		String returnStr = null;
		if(null != retStr && retStr.trim().length() > 500){
			returnStr = retStr.substring(0, 500);
		}else{
			returnStr = retStr;
		}
		if(null != exceptionMes && exceptionMes.trim().length() > 500){
			exceptionMes = exceptionMes.substring(0, 500);
		}
		printElkLog(url,body,costTime,exceptionMes,returnStr,netIp,"未获取",null);
		return retStr;
	}
	
	public static String doPost1(String url, String ctype, byte[] content,
			int connectTimeout, int readTimeout,String netIp) throws Exception {
		HttpsURLConnection conn = null;
		OutputStream out = null;
		String rsp = null;
		try {
			try {
				SSLContext ctx = SSLContext.getInstance("TLSv1.2");
				/*ctx.init(new KeyManager[0],
				new TrustManager[] { new DefaultTrustManager() },
				new SecureRandom());*/
				TrustManager[] trustAllCerts = {new TrustAllTrustManager()};
				ctx.init(new KeyManager[0],trustAllCerts,new SecureRandom());
				SSLContext.setDefault(ctx);

				conn = getConnection1(new URL(url), METHOD_POST, ctype,netIp);
				conn.setHostnameVerifier(new HostnameVerifier() {
					@Override
					public boolean verify(String hostname, SSLSession session) {
						return true;
					}
				});
				conn.setConnectTimeout(connectTimeout);
				conn.setReadTimeout(readTimeout);
			} catch (Exception e) {
				throw e;
			}
			try {
				out = conn.getOutputStream();
				out.write(content);
				rsp = getResponseAsString1(conn);
			} catch (IOException e) {
				throw e;
			}

		} finally {
			if (out != null) {
				out.close();
			}
			if (conn != null) {
				conn.disconnect();
			}
		}

		return rsp;
	}
	
	protected static String getResponseAsString1(HttpURLConnection conn)
			throws Exception {
		String charset = getResponseCharset(conn.getContentType());
		InputStream es = conn.getErrorStream();
		if (es == null) {
			return getStreamAsString(conn.getInputStream());
		} else {
			String msg = getStreamAsString(es);
			
			return msg;//直接返回错误结果
		}
	}

	private static HttpsURLConnection getConnection1(URL url, String method,
			String ctype,String netIp) throws IOException {
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		conn.setRequestMethod(method);
		conn.setDoInput(true);
		conn.setDoOutput(true);
		conn.setRequestProperty("Accept", "*/*");
		conn.setRequestProperty("User-Agent", "stargate");
		conn.setRequestProperty("Content-Type", ctype);
		if(null != netIp && IpUtils.isRightIP(netIp)){
			conn.setRequestProperty("x-forwarded-for", netIp);
		}
		return conn;
	}
	public static void main(String[] args) {
		/*String url = "https://yun.syn.cn/index.php?r=api/school/getplatformcode";
		JSONObject obj = new JSONObject();
		obj.put("domain", "yun.syn.cn");
		String resp = null;
		try {
			resp = doPost(url ,obj.toJSONString());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("resp="+resp);
		
		String url = "https://aamif.syn.cn/aamif/rest/queryClassStudentReq?token=";
		JSONObject obj = new JSONObject();
		obj.put("classid", "f1a45babd1f645d9b4b1bcd118a6696f");
		obj.put("start", 0);
		obj.put("end", 2147483647);
		String resp = null;
		try {
			resp = doPost(url ,obj.toJSONString());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("resp="+resp);*/
		
		String url = "https://aamif.syn.cn/aamif/rest/user/0b32f8ed1aca494ba69a629ccf792cf2";
		String resp = null;
		try {
			resp = doGet(url,null);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("resp="+resp);
	}
	
	private static void printElkLog(String url, String body, String costTime, String exceptionMes, String returnStr,
			String netIp, String responseStatus,Map<String, String> headers) {
		if(null != body){
			body = body.replace("\"","\\\"");
		}
		if(null != returnStr){
			returnStr = returnStr.replace("\"","\\\"");
		}
		MDC.put("url",url);
		MDC.put("body",body);
		MDC.put("costTime",costTime);
		MDC.put("exceptionMes",exceptionMes);
		MDC.put("responseStatus", responseStatus);
		MDC.put("description",returnStr);
		MDC.put("requestIp",netIp);
		if(null!=headers && headers.size()>0){
			MDC.put("requestHeader", ((JSONObject)JSONObject.toJSON(headers)).toJSONString().replace("\"","\\\""));
		}
		logger.error("外部接口请求信息");
	}

}
